package com.xh.baselibrary.tts;


import com.xh.baselibrary.log.XLog;

/**
 * 音频缓存队列
 * 按指定容量填充
 */
public class AudioBuffer {
    private Segments first;
    private final int buffSize;
    private volatile int itemSize;
    private int MAX_SIZE = 15;

    public AudioBuffer(int segmentsSize, int maxItemSize) {
        XLog.i("AudioBuffer", "segmentsSize--->" + segmentsSize);
        this.buffSize = segmentsSize;
        MAX_SIZE = maxItemSize;
    }

    public AudioBuffer(int segmentsSize) {
        XLog.i("AudioBuffer", "segmentsSize--->" + segmentsSize);
        this.buffSize = segmentsSize;
    }

    public void push(short[] array) {
        if (array == null || array.length == 0) return;
        synchronized (AudioBuffer.this) {
            if (itemSize >= MAX_SIZE) {
                pop();
            }
            if (first == null) first = new Segments(buffSize);
            first.push(array);
        }
    }

    public synchronized short[] pop() {
        if (first != null) {
            Segments f = first.pop();
            short[] data = f.getAvailable();
            f.buff = null;
            f = null;
            return data;
        }
        return null;
    }


    public synchronized int size() {
        return itemSize;
    }

    public synchronized boolean hasPop() {
        return itemSize > 1;
    }

    public synchronized boolean isEmpty() {
        return itemSize == 0;
    }

    public synchronized void clear() {
        for (Segments f = first; f != null; ) {
            Segments next = f.next;
            f.buff = null;
            f.next = null;
            f = next;
        }
        first = null;
        itemSize = 0;
    }

    public synchronized int length() {
        int len = 0;
        for (Segments f = first; f != null; ) {
            len += f.pos;
            f = f.next;
        }
        return len;
    }

    private class Segments {
        short[] buff;
        private int pos = 0;
        private final int size;
        Segments next = null;

        Segments(int size) {
            this.size = size;
            buff = new short[size];
            itemSize++;
        }

        void push(short[] array) {
            int len = array.length;
            if (pos + len >= size) {
                //剩余容量
                int capacity = size - pos;
                short[] cap;
                if (capacity > 0) {
                    System.arraycopy(array, 0, buff, pos, capacity);
                    pos += capacity;
                    int res = len - capacity;
                    cap = new short[res];
                    System.arraycopy(array, capacity, cap, 0, res);
                } else {
                    cap = array;
                }
                if (next == null) {
                    next = new Segments(size);
                }
                next.push(cap);
            } else {
                //容量充足
                System.arraycopy(array, 0, buff, pos, len);
                pos += len;
            }
        }

        boolean limit() {
            return pos == size;
        }

        short[] getAvailable() {
            if (limit()) {
                return buff;
            }
            short[] available = new short[pos];
            System.arraycopy(buff, 0, available, 0, pos);
            return available;
        }

        Segments pop() {
            if (next != null) {
                first = next;
                next = null;
            } else {
                first = null;
            }
            itemSize--;
            return this;
        }

        void recycle(){

        }
    }

    private class SegmentsPool{

    }
}
